package com.cx.mall.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cx.mall.api.goods.SkuInfoFeign;
import com.cx.mall.common.model.goods.Stock;
import com.cx.mall.common.model.order.OrderDTO;
import com.cx.mall.common.model.order.OrderDetail;
import com.cx.mall.common.model.order.OrderInfo;
import com.cx.mall.common.model.order.OrderQuery;
import com.cx.mall.common.utils.ResponseEnum;
import com.cx.mall.common.utils.ResponseVO;
import com.cx.mall.order.service.IOrderDetailService;
import com.cx.mall.order.service.IOrderInfoService;
import com.cx.mall.order.service.IOrderService;
//import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

//@GlobalTransactional//(rollbackFor = Exception.class,timeout = 1
//        ,isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED)
@Service
public class OrderServiceImpl implements IOrderService {
    @Autowired
    private IOrderInfoService orderInfoService;
    @Autowired
    private IOrderDetailService orderDetailService;
    @Autowired
    private SkuInfoFeign skuInfoFeign;
    @Autowired
    private StreamBridge streamBridge;
    @Autowired
    private RedisTemplate redisTemplate;
    @Override
    @Transactional
    public OrderInfo save(OrderDTO order) throws RuntimeException {
        // 1. 保存订单详情
        // 1.1 生成订单编号
        String orderId = IdWorker.getIdStr();
        // 1.2 获取订单详情
        List<OrderDetail> orderDetails = order.getOrderDetails();
        // 2.3 获取订单Id和计算合计，总计金额
        BigDecimal totalAmount = new BigDecimal(0); // 总计金额
        for (OrderDetail orderDetail : orderDetails) {
            // 设置订单Id
            orderDetail.setOrderId(orderId);
            // 计算合计
            BigDecimal amount =  orderDetail.getPrice().multiply(new BigDecimal(orderDetail.getQuantity()));
            orderDetail.setAmount(amount);
            // 总计金额
            totalAmount = totalAmount.add(amount);
        }
        // 2.4 保存订单详情
        orderDetailService.saveBatch(orderDetails);
        // 2. 保存订单信息
        // 1.1 获取订单信息
        OrderInfo orderInfo = JSON.parseObject(JSON.toJSONString(order), OrderInfo.class);
        orderInfo.setOrderId(orderId);
        orderInfo.setTotalAmount(totalAmount);
        // 1.2 保存订单
        orderInfoService.save(orderInfo);
        //库存递减
        //获取递减库存商品
        List<Stock> stocks = JSON.parseArray(JSON.toJSONString(orderDetails), Stock.class);
        //调用递减库存
        ResponseVO skuResult = skuInfoFeign.decreaseStock(stocks);
        if(skuResult.getCode() != ResponseEnum.SUCCESS.getCode()){
            throw new RuntimeException(skuResult.getMessage());
        }


        //4.删除购物车
        List<String> cartIds = order.getCartIds();
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                Message<?> message = MessageBuilder
                        .withPayload(JSON.toJSONString(cartIds))
                        .setHeader("TRANSACTION_ID", orderId)
                        .build();

                // 构建去重键，使用orderId确保唯一性
                String uniqueKey = "CART_DELETE_" + orderId;

                // 设置Redis键值对，只有当键不存在时才会设置成功
                // 同时设置10分钟过期时间，避免键永久留存
                if (redisTemplate.opsForValue().setIfAbsent(uniqueKey, "1", 10, TimeUnit.MINUTES)) {
                    streamBridge.send("deleteCart-out-0", message);
                }
            }
        });
        // 5.下单回查
        // 5.1 以orderId和userId去重
        String id = orderId + orderInfo.getUserId();
        // 5.2 发送支付回查请求
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                Message<?> message = MessageBuilder
                        .withPayload(orderId)
                        .setHeader("TRANSACTION_ID",orderId)
                        .setHeader("DELAY", 5).build();
                if(redisTemplate.opsForValue().setIfAbsent("REQ_" + id,"1",60, TimeUnit.SECONDS)){
                    streamBridge.send("checkPayOutput-out-0", message);
                }
            }
        });

        return orderInfo;
    }

    @Transactional(readOnly = true)
    @Override
    public Page page(OrderQuery query) {
        //1、查询订单信息
        Page page = orderInfoService.page(query);
        if(page.getTotal() > 0){
            //如果查询记录不为空，才会获取订单数据
            List<OrderDTO> records = page.getRecords();
            List<String> ids = records.stream().map(OrderInfo::getOrderId).collect(Collectors.toList());
            //获取所有订单的详情
            List<OrderDetail> details = orderDetailService.listByOrderIds(ids);

            List<OrderDTO> data = records.stream().map(orderInfo -> {
                //筛选每个订单的订单详情
                List<OrderDetail> collect = details.stream().filter(detail -> detail.getOrderId().equals(orderInfo.getOrderId())).collect(Collectors.toList());
                //将orderInfo转化成orderDTO
                OrderDTO orderDTO = JSON.parseObject(JSON.toJSONString(orderInfo), OrderDTO.class);
                orderDTO.setOrderDetails(collect);
                return orderDTO;
            }).collect(Collectors.toList());
            page.setRecords(data);
            return page;
        }
        return null;
    }

    @Override
    @Transactional
    public void removeById(String id) {
        orderInfoService.removeById(id);
        orderDetailService.removeByOrderId(id);
    }



}
